module FSM #(
	parameter F1 =    	  6'd1,
	parameter F2 =    	  6'd2,
	parameter Decode_tmp= 6'd3,
	parameter Decode =	  6'd4,
	parameter EA =    	  6'd5,
	parameter Ex =    	  6'd6,
	parameter WB =    	  6'd7,
	parameter OP_read=	  6'd8,
	parameter MEM_WB=     6'd9	
	
) (
	CLK,Reset,INSTR,INSTR_5,PCSEL,LD_PC,ADDR1MUX_SEL,ADDR2MUX_SEL,MARMUX_SEL,tri_PC_SEL,LD_MAR,RAM_WE,MDR_SEL,LD_MDR,tri_RAM_SEL,LD_IR,LD_Registerfile,SR2MUX_SEL,ALU_SEL,tri_ALU_SEL,SR1,SR2,DR
);
	//Def port definition!
	reg [5:0] current_state,next_state;
	input CLK,Reset;
	input [15:0] INSTR;
	input INSTR_5;
	output LD_PC,ADDR1MUX_SEL,MARMUX_SEL,tri_PC_SEL,LD_MAR,RAM_WE,MDR_SEL,LD_MDR,tri_RAM_SEL,LD_IR,LD_Registerfile,SR2MUX_SEL;
	output [1:0] ADDR2MUX_SEL; 
	output  tri_ALU_SEL;
	output  [1:0] PCSEL;
	output reg [2:0] ALU_SEL;
	output reg [2:0] SR1,SR2,DR;

	//Def local variable!
	wire [3:0] OPCODE;
	reg [18:0] CURRENT_SIGNALS;

	assign OPCODE=INSTR[15:12];
	assign PCSEL=CURRENT_SIGNALS[18:17];//四种模式
	assign LD_PC=CURRENT_SIGNALS[16];//高电平有效
	assign ADDR1MUX_SEL=CURRENT_SIGNALS[15];//不同通道选择
	assign ADDR2MUX_SEL=CURRENT_SIGNALS[14:13];
	assign MARMUX_SEL=CURRENT_SIGNALS[12];//1信号端才有接东西
	assign tri_PC_SEL=CURRENT_SIGNALS[11];//高电平有效
	assign LD_MAR=CURRENT_SIGNALS[10];
	assign RAM_WE=CURRENT_SIGNALS[9];//写使能信号
	assign MDR_SEL=CURRENT_SIGNALS[8];
	assign LD_MDR=CURRENT_SIGNALS[7];
	assign tri_RAM_SEL=CURRENT_SIGNALS[6];
	assign LD_IR=CURRENT_SIGNALS[5];
	assign LD_Registerfile=CURRENT_SIGNALS[4];
	assign SR2MUX_SEL=CURRENT_SIGNALS[3];
	assign tri_ALU_SEL=CURRENT_SIGNALS[2];

	always @(posedge CLK or negedge Reset) begin
		if (Reset==1'b1) begin
			current_state<=F1;//F1 means Idle 初始化	
		end else begin
			current_state<=next_state;
		end
	end
	always @(INSTR or current_state or Reset) begin
		if (Reset==1'b1) begin
			CURRENT_SIGNALS = 19'b11_1_0_00_0_1_00000000000;
			//CURRENT_SIGNALS = 19'b11_0_1_00_1_0_1_000_000_0000;//初始态还有待思考
			next_state = F1;
		end
		else begin
		CURRENT_SIGNALS = {19{1'b0}};
		$display("\n %m: At time %0t : current_state = %d",$time,current_state);
		case (current_state)
			F1:		//F1-00,the first step of fetch instruction;MAR<=PC;PC<=PC+1
				begin
					/*PC_SEL<=2'b00;
					  LD_PC<=1'b0;
					  ADDR1MUX_SEL<=1'b1;
					  ADDR2MUX_SEL<=2'b00;
					  MARMUX_SEL<=1'b1;
					  tri_PC_SEL<=1'b1;
					  LD_MAR<=1'b1;
CURRENT_SIGNALS = {PC_SEL[18:17],LD_PC[16],ADDR1MUX_SEL[15],ADDR2MUX_SEL[14:13],MARMUX_SEL[12],tri_PC_SEL[11],LD_MAR[10]}*/
					CURRENT_SIGNALS = 19'b00_0_1_00_1_1_1_000_000_0000;
					next_state = F2;
				end
			F2:		//F2-01,the sercond step of fetch instruction; MDR<=RAM[MAR]
				begin
					/*
					  LD_PC<=1'b1;
					  tri_PC_SEL<=1'b0;
					  LD_MAR<=1'b1;
					  RAM_WE<=1'b0;//WE = Write_Enable, this operation is "read the ram"
					  MDR_SEL<=1'b0;
					  LD_MDR<=1'b1;
					  tri_RAM_SEL<=1'b1;
					  LD_IR<=1'b1;
					  LD_PC<=1'b1;
CURRENT_SIGNALS = {PC_SEL[18:17],LD_PC[16],ADDR1MUX_SEL[15],ADDR2MUX_SEL[14:13],MARMUX_SEL[12],tri_PC_SEL[11],LD_MAR[10],
				   RAM_WE[9],MDR_SEL[8],LD_MDR[7],tri_RAM_SEL[6],LD_IR[5]}*/
 					//CURRENT_SIGNALS = 19'b00_1_1_00_1_0_1_001_110_0000;
 					CURRENT_SIGNALS = 19'b00_0_1_00_1_0_1_001_110_0000;
					next_state = Decode_tmp;	
				end
			Decode_tmp:
				begin
					CURRENT_SIGNALS = 19'b00_0_1_00_1_0_1_000_110_0000;
					next_state = Decode;
				end
			Decode:  //Decode-02, decode the op_code [15:12],有问题！！	
				begin
 					CURRENT_SIGNALS = 19'b00_0_1_00_1_0_1_000_110_0000;	
				$display("%m: At time %0t : OPCODE = %b",$time,OPCODE);
				if ((OPCODE[1:0] == 2'b10 | OPCODE[1:0] == 2'b11) & OPCODE != 4'b1111)begin
					$display("%m: At time %0t : OPCODE = %b",$time,OPCODE);
					next_state = EA;//EA=Execute Address, LD&ST
				end else begin
					//CURRENT_SIGNALS<=19'b00_0_1_00_1_0_1_0_0_1_1_0_00000;
					next_state = Ex;

					//set ALU mode
					ALU_SEL = INSTR[15:14];

					//source register
					SR1 = INSTR[8:6];
                    SR2 = INSTR[2:0];

					//Destination register
					if (OPCODE==4'b0100) begin//instruction: JSR??
						DR<=3'b111;
					end 
					else begin
					DR = INSTR[11:9];
					end
				end
			end	
			Ex:	//Ex-03, Execute the instruction
				begin 
					//tri_RAM_SEL<=1'b0;
					if (OPCODE==4'b0001) 
						begin //Opcode = ADD
						//LD_Registerfile<=1'b0;//SRC1+SRC2=>OUT
						//SR2MUX_SEL<=1'b1;select SEXT4
						//tri_ALU_SEL<=1'b1;
/*CURRENT_SIGNALS = {PC_SEL[18:17],LD_PC[16],ADDR1MUX_SEL[15],ADDR2MUX_SEL[14:13],MARMUX_SEL[12],tri_PC_SEL[11],LD_MAR[10],
				     RAM_WE[9],MDR_SEL[8],LD_MDR[7],tri_RAM_SEL[6],LD_IR[5],LD_Registerfile[4],SR2MUX_SEL[3],tri_ALU_SEL[2]}*/
						CURRENT_SIGNALS = 19'b00_0_0_00_0_0_0_0_0_0_0_0_0_1_1_00;
						next_state = WB;
						end
					else if (OPCODE==4'b0101) begin//OPcode = AND
								//LD_Register<=1'b0;//SRC1&SRC2
						CURRENT_SIGNALS = 19'b00_0_0_00_0_0_0_0_0_0_0_0_0_1_1_00;
						next_state = WB;
					end
					else next_state = F1;
				end
			WB:	//WB-04, Write back the data into the register
				begin
					//LD_IR<=1'b1;
					//tri_ALU_SEL<=1'b1
/*CURRENT_SIGNALS = {PC_SEL[18:17],LD_PC[16],ADDR1MUX_SEL[15],ADDR2MUX_SEL[14:13],MARMUX_SEL[12],tri_PC_SEL[11],LD_MAR[10],
				     RAM_WE[9],MDR_SEL[8],LD_MDR[7],tri_RAM_SEL[6],LD_IR[5],LD_Registerfile[4],SR2MUX_SEL[3],tri_ALU_SEL[2]}*/
					CURRENT_SIGNALS = 19'b00_1_00_000_000_00_1_1_1_1_00;
					next_state = F1;
				end
			EA:	//EA-Execute Address

				//ADDR1MUX_SEL=1;
				//ADDR2MUX_SEL=01;
				//MARMUX_SEL=1;
				//tri_PC_SEL=1;
				//LDMAR=1;
				//MDR_SEL=0;
				//LDMDR=1;
				begin
/*CURRENT_SIGNALS = {PC_SEL[18:17],LD_PC[16],ADDR1MUX_SEL[15],ADDR2MUX_SEL[14:13],MARMUX_SEL[12],tri_PC_SEL[11],LD_MAR[10],
				     RAM_WE[9],MDR_SEL[8],LD_MDR[7],tri_RAM_SEL[6],LD_IR[5],LD_Registerfile[4],SR2MUX_SEL[3],tri_ALU_SEL[2]}*/
					CURRENT_SIGNALS = 19'b00_0_1_01_1_1_1_0_0_1_0000000;
					next_state<=OP_read;//ADDR1MUX=1,ADDR2MUX=01
				end
			OP_read:
				begin
					CURRENT_SIGNALS = 19'b00_0_1_01_1_0_1_0_0_1_1_0_10000;
					next_state<=MEM_WB;
				end
			MEM_WB:
				begin
					CURRENT_SIGNALS = 19'b00_1_1_01_1_0_1_0_0_1_1_0_10000;
					next_state<=F1;
				end
			default: begin
				next_state = F1;
			end
		endcase
		end
	end
endmodule
